///@file MVData.h CMVData 类定义文件
#ifndef _MVDATA_H_
#define _MVDATA_H_

#include <list>
#include <string>
#include "MVDataFrame.h"

class CMVDataAgent;

// TODO: namespace?
///@brief 将整个的MVData进行封装，隐藏真实数据操作方式。
class CMVData
{
	friend class CMVDataXML;
	friend class CMVDataAgent;
	friend class CMVDataAgentXML;

//============================== 一般方法 ====================================
public:
	///@brief 构造函数，创建后会自动调用Open方法
	///@see CMVData::Open()
	///@param type 使用的持久化方式
	///@param dataname 数据的唯一标示，当使用TYPE_MVDATA_XML时，表示数据文件名
	CMVData( TYPE_MVDATA_STORE type, const std::string dataname );

	///@brief 默认构造函数，创建后使用Open方法或者CreateNew方法打开MV数据
	CMVData();

	///@brief 析构函数
	~CMVData();

public:
	///@brief 打开一个已经存在的数据，并读入其内容，如果数据不存在则创建。在同一个运行期中同一个文件不能同时打开两次
	///@param type 使用的持久化方式
	///@param dataname 数据的唯一标示，当使用TYPE_MVDATA_XML时，表示数据文件名
	///@retval 0 成功
	///@retval -1 失败
	int Open( TYPE_MVDATA_STORE type, const std::string dataname );

	///@brief 创建一个数据，如果对应数据已经存在，则清除其内容
	///@param type 使用的持久化方式
	///@param dataname 数据的唯一标示，当使用TYPE_MVDATA_XML时，表示数据文件名
	///@param width 图像一帧的宽度
	///@param width 图像一帧的高度
	int CreateNew( TYPE_MVDATA_STORE type, const std::string dataname, int width = 0, int height = 0 );

	///@brief 结束使用此CMVData中的数据，如果对数据有修改，则会写回
	int Close();

	///@brief 清空所有的数据
	int Clear();

	///@brief 检查当前是否有已经打开合法的数据
	bool IsDataReady() const;

public:
	///@brief 重载=操作符，将复制所有内部数据
	CMVData& operator =( const CMVData& mvdata );

//============================== 属性方法 ====================================
public:
	///@brief 设置一帧图像的长度和宽度
	int SetFrameSize( int width, int height );
	///@brief 取得一帧的宽度
	int GetFrameWidth() const;
	///@brief 取得一帧的高度
	int GetFrameHeight() const;

	///@brief 设置读操作的默认Frame
	int ReadFrame( int frame_number );
	///@brief 设置写操作的默认Frame
	int WriteFrame( int frame_number );

	///@brief 取得指定帧的类型
	TYPE_FRAME GetFrameType( int frame_number = -1 ) const;
	///@brief 设置指定帧的类型
	int SetFrameType( TYPE_FRAME frame_type, int frame_number = -1 );

	///@brief 根据MB位置以及Frame号取得相应的CMVDataMB，frame_number不指定时，返回上次使用的帧号，失败返回NULL
	const CMVDataMB * GetMB( int x, int y, int frame_number = -1 ) const;

	// TODO: should this method preserved?
	///@brief 取得给定的mb的下一个MB，frame_number不指定时，返回上次使用的帧号，失败返回NULL
	///retval NULL 失败
	const CMVDataMB * GetNextMB( const CMVDataMB * curr_mb, int frame_number = -1 ) const;

	///@brief 向CMVData中添加一个新的CMVDataMB
	///@param mb 要添加的CMVDataMB类型的指针
	///@param frame_number 将mb加到哪个Frame上，-1表示默认Frame
	int AddMB( const CMVDataMB * mb, int frame_number = -1 );
	///@brief 删除指定的CMVDataMB
	int RemoveMB( int x, int y, int frame_number = -1 ); 

	///@brief 取得帧的数目
	int GetFrameCount() const;
	///@brief 取得指定帧中的Macro Block数目
	int GetMBCount( int frame_number = -1 ) const;

	///@brief 取得数据标示名
	const std::string GetDataName() const;

private:
	///@brief 通过帧号取得对应帧
	CMVDataFrame * _GetFrameByNumber( int frame_number ) const;

	///@brief 用于迭代访问所有的帧，当curr_frame==NULL时，返回第一帧
	const CMVDataFrame * GetNextFrame( const CMVDataFrame * curr_frame ) const;

	///@brief 加入一个新的帧，在内部按帧号大小升序排序
	int AddFrame( const CMVDataFrame * framedata );

	///@brief 通过帧号删除对应帧
	int RemoveFrameByNumber( int framenumber );

private:
	///@brief 读入打开的数据
	int ReadAll();
	///@brief 写入数据
	int WriteAll();
	
	///@brief 将参数中传入的帧号转化为实际帧号
	CMVDataFrame * _GetRealFrameForRead( int frame_number ) const;
	CMVDataFrame * _GetRealFrameForWrite( int frame_number ) const;

//============================== 类成员 ====================================
private:
	std::string m_strDataName;
	std::list<CMVDataFrame*> * m_plstFrame;
	CMVDataAgent * m_pAgent;

	int m_iLastReadFrameNumber;
	int m_iLastWriteFrameNumber;

	bool m_bModified;
	bool m_bReadyToUse;

	int m_iFrameHeight;
	int m_iFrameWidth;

	static std::list<std::string> m_lstOpenedDataName;

};



#endif // _MVDATA_H_